package com.raorao.rpc.config;

import com.raorao.rpc.client.ClientProxyFactory;
import com.raorao.rpc.client.discovery.ServiceDiscoverer;
import com.raorao.rpc.client.discovery.ZookeeperServiceDiscoverer;
import com.raorao.rpc.client.net.NettyNetClient;
import com.raorao.rpc.common.constants.ProtocolEnum;
import com.raorao.rpc.common.protocol.JavaSerializeMessageProtocol;
import com.raorao.rpc.common.protocol.MessageProtocol;
import com.raorao.rpc.common.utils.EventPushUtil;
import com.raorao.rpc.common.utils.LoadBalanceUtils;
import com.raorao.rpc.listener.ServiceChangeListener;
import com.raorao.rpc.properties.RpcProperty;
import com.raorao.rpc.server.NettyRpcServer;
import com.raorao.rpc.server.RequestHandler;
import com.raorao.rpc.server.RpcServer;
import com.raorao.rpc.server.register.DefaultRpcProcessor;
import com.raorao.rpc.server.register.ServiceRegister;
import com.raorao.rpc.server.register.ZookeeperExportServiceRegister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;

/**
 * Spring boot 自动配置类
 *
 * @author raorao
 * @since 1.0.0
 */
@Configuration
@EnableAsync
public class AutoConfiguration {

    private static Logger logger = LoggerFactory.getLogger(AutoConfiguration.class);

    @Bean
    public DefaultRpcProcessor defaultRpcProcessor() {
        return new DefaultRpcProcessor();
    }

    @Bean
    public ClientProxyFactory clientProxyFactory(@Autowired RpcProperty rpcProperty) {
        ClientProxyFactory clientProxyFactory = new ClientProxyFactory();
        // 设置服务发现者
        clientProxyFactory.setServiceDiscoverer(this.serviceDiscoverer(rpcProperty));
        logger.debug("【raorao-rpc】设置服务发现者");
        // 设置支持的协议
        Map<String, MessageProtocol> supportMessageProtocols = new HashMap<>();
        supportMessageProtocols.put(rpcProperty.getProtocol(), new JavaSerializeMessageProtocol());
        clientProxyFactory.setSupportMessageProtocols(supportMessageProtocols);
        logger.debug("【raorao-rpc】设置支持的协议");
        // 设置网络层实现
        clientProxyFactory.setNetClient(new NettyNetClient());
        logger.debug("【raorao-rpc】设置网络层实现");
        return clientProxyFactory;
    }

    /**
     * 根据参数获取服务发现者
     * @param rpcProperty 参数
     * @return ServiceDiscoverer
     */
    private ServiceDiscoverer serviceDiscoverer(RpcProperty rpcProperty){
        ServiceDiscoverer serviceDiscoverer=null;
        switch (ProtocolEnum.fromString(rpcProperty.getProtocol())){
            case ZOOKEPPER:{
                serviceDiscoverer=new ZookeeperServiceDiscoverer(rpcProperty.getRegisterAddress());
                break;
            }
            default:{
                serviceDiscoverer=new ZookeeperServiceDiscoverer(rpcProperty.getRegisterAddress());
                break;
            }
        }
        return serviceDiscoverer;
    }

    /**
     * 根据参数获取服务注册者
     * @param rpcProperty 参数
     * @return ServiceDiscoverer
     */
    @Bean
    public ServiceRegister serviceRegister(@Autowired RpcProperty rpcProperty) {
        ServiceRegister serviceRegister=null;
        switch (ProtocolEnum.fromString(rpcProperty.getProtocol())){
            case ZOOKEPPER:{
                serviceRegister=new ZookeeperExportServiceRegister(
                        rpcProperty.getRegisterAddress(),
                        rpcProperty.getServerPort(),
                        rpcProperty.getProtocol());
                break;
            }
            default:{
                serviceRegister=new ZookeeperExportServiceRegister(
                        rpcProperty.getRegisterAddress(),
                        rpcProperty.getServerPort(),
                        rpcProperty.getProtocol());
                break;
            }
        }
        return serviceRegister;
    }

    @Bean
    public RequestHandler requestHandler(@Autowired ServiceRegister serviceRegister) {
        return new RequestHandler(new JavaSerializeMessageProtocol(), serviceRegister);
    }

    @Bean
    public RpcServer rpcServer(@Autowired RequestHandler requestHandler,
                               @Autowired RpcProperty rpcProperty) {
        return new NettyRpcServer(rpcProperty.getServerPort(),
                rpcProperty.getProtocol(), requestHandler);
    }

    @Bean
    public RpcProperty rpcProperty() {
        RpcProperty rpcProperty = new RpcProperty();
        return rpcProperty;
    }

    @Bean("rpcExecutor")
    public Executor asyncServiceExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(3);
        // 设置最大线程数
        executor.setMaxPoolSize(5);
        //配置队列大小
        executor.setQueueCapacity(Integer.MAX_VALUE);
        // 设置线程活跃时间（秒）
        executor.setKeepAliveSeconds(60);
        // 设置默认线程名称
        executor.setThreadNamePrefix("rpcThreadPool");
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //执行初始化
        executor.initialize();
        return executor;
    }

    @Bean
    public ServiceChangeListener serviceChangeListener(){
        return new ServiceChangeListener();
    }

    @Bean
    public EventPushUtil eventPushUtil(){
        return new EventPushUtil();
    }

    @Bean
    public LoadBalanceUtils loadBalanceUtils(@Autowired RpcProperty rpcProperty){
        return new LoadBalanceUtils(rpcProperty);
    }
}
